/**
 * @file lettori_scrittori.h
 *
 * @author Federico Consoli
 *
 * Released under GNU GPLv3 (http://www.gnu.org/licenses/gpl-3.0.txt)
 */

#ifndef LETTORI_SCRITTORI_H
#define	LETTORI_SCRITTORI_H
#include <pthread.h>


/**
 * @page lettori_scrittori  lettori_scrittori 
 * @section Readers-writers Readers-writers problem class info
 * 
 * A solution with fairness for both readers and writers might be as follows:
 * \code
 *       semaphores: no_writers, no_readers, counter_mutex ( initial value is 1 ) 
 *       shared variables: nreaders ( initial value is 0 ) 
 *       local variables:  prev, current
 * \endcode
 *
 * WRITER: \n
 * \code
 *       P( no_writers ); 
 *         P( no_readers ); 
 *         V( no_readers ); 
 *         ...  write ... 
 *       V( no_writers ); 
 * \endcode
 * READER: \n
 * \code
 *       P( no_writers ); 
 *         P( counter_mutex ); 
 *           prev := nreaders; 
 *           nreaders := nreaders + 1; 
 *         V( counter_mutex ); 
 *         if prev = 0  then P( no_readers ); 
 *       V( no_writers ); 
 *       ... read ... 
 *       P( counter_mutex ); 
 *         nreaders := nreaders - 1; 
 *         current := nreaders; 
 *       V( counter_mutex ); 
 *       if current = 0 then V( no_readers ); 
 * \endcode
 *  
 */

/** 
 * 
 * Implementation of the Lettori_scrittori class.
 * It solve the readers-writers problem. It allow multiple readers and single
 * write without starvation. It adds the constraint that no thread shall be 
 * allowed to starve; that is, the operation of obtaining a lock on 
 * the shared data will always terminate in a bounded amount of time.
 * For more info see @link lettori_scrittori @endlink page
 */
class Lettori_scrittori {
    /** Write lock */
    pthread_mutex_t lettura;
    /** Read lock */
    pthread_mutex_t scrittura;
    /** Counter lock*/
    pthread_mutex_t counter;
    /** Number of readers */
    int nreaders;

public:
    /**
     * Constructor, it initialize semaphore.
     */
    Lettori_scrittori();
    /**
     * Destroy. It destroy semaphore
     */
    ~Lettori_scrittori();

    /** Start a read */
    void leggi_begin();
    //leggi..

    /** End a read */
    void leggi_end();

    /** Start a write */
    void scrivi_begin();
    //scrivi....

    /** End a write */
    void scrivi_end();

};

#endif	/* LETTORI_SCRITTORI_H */

